package com.hivekion.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hivekion.common.core.SystemConstant;
import com.hivekion.common.entity.TreeNode;
import com.hivekion.common.exception.BusinessException;
import com.hivekion.common.redis.RedisUtil;
import com.hivekion.system.domain.SysDept;
import com.hivekion.system.domain.SysUser;
import com.hivekion.system.domain.vo.SysDeptCreateInputVo;
import com.hivekion.system.domain.vo.SysDeptModelVo;
import com.hivekion.system.domain.vo.SysDeptUpdateInputVo;
import com.hivekion.system.domain.vo.SysDeptViewVo;
import com.hivekion.system.mapper.SysDeptMapper;
import com.hivekion.system.mapper.SysUserMapper;
import com.hivekion.system.service.ISysDeptService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysDeptServiceImpl implements ISysDeptService {

      @Autowired
      SysUserMapper userMapper;
      @Autowired
      private SysDeptMapper deptMapper;
      @Autowired
      private RedisUtil redisUtil;

      @Override
      public Boolean checkDeptNameUnique(String deptName, String deptId) {
	    LambdaQueryWrapper<SysDept> deptLambdaQueryWrapper = Wrappers.lambdaQuery();
	    deptLambdaQueryWrapper.eq(SysDept::getDeptName, deptName);
	    if (StringUtils.isNotEmpty(deptId)) {
		  deptLambdaQueryWrapper.ne(SysDept::getId, deptId);
	    }
	    List<SysDept> list = deptMapper.selectList(deptLambdaQueryWrapper);
	    return list.size() > 0;
      }

      @Override
      public boolean create(SysDeptCreateInputVo inputVo) {
	    SysDept dept = new SysDept();
	    BeanUtils.copyProperties(inputVo, dept);
	    if (inputVo.getParentId() == null) {
		  dept.setParentId("");
	    }
	    boolean bl = deptMapper.insert(dept) > 0;
	    if (bl) this.updateRedis();
	    return bl;
      }

      @Override
      public boolean update(SysDeptUpdateInputVo inputVo) {
	    SysDept dept = getDept(inputVo.getId());
	    BeanUtils.copyProperties(inputVo, dept);
	    boolean bl = deptMapper.updateById(dept) > 0;
	    if (bl) this.updateRedis();
	    return bl;
      }

      @Override
      public SysDeptModelVo getDeptInfo(String deptId) {
	    SysDept dept = deptMapper.selectById(deptId);
	    if (dept == null) {
		  throw new BusinessException(500, "未找到部门信息！");
	    }
	    SysDeptModelVo vo = new SysDeptModelVo();
	    BeanUtils.copyProperties(dept, vo);
	    return vo;
      }

      @Override
      public boolean delete(String deptId) {
	    List<SysDept> children = getChildren(deptId);
	    if (children.size() > 0) {
		  throw new BusinessException(500, "该部门下还有部门");
	    }
	    boolean bl = deptMapper.deleteById(deptId) > 0;
	    if (bl) this.updateRedis();
	    return bl;
      }

      @Override
      public boolean changeStatus(String deptId, Integer status) {
	    SysDept dept = getDept(deptId);
	    dept.setStatus(status);
	    boolean bl = deptMapper.updateById(dept) > 0;
	    if (bl) this.updateRedis();
	    return bl;
      }

      @Override
      public List<SysDeptViewVo> getList() {
	    return buildViewVo(getParentDepts());
      }

      private List<SysDeptViewVo> buildViewVo(List<SysDept> list) {
	    List<SysDeptViewVo> nodes = new ArrayList<>();
	    if (list != null && list.size() > 0) {
		  list.forEach(
			  dept -> {
				SysDeptViewVo vo = new SysDeptViewVo();
				BeanUtils.copyProperties(dept, vo);
				String leader = dept.getLeader();
				SysUser leaderU = userMapper.selectById(dept.getLeader());
				if (leaderU != null) {
				      vo.setLeader(leaderU.getUserName());
				} else {
				      vo.setLeader("-");
				}
				vo.setChildren(null);
				List<SysDeptViewVo> vos = getChilderenVo(dept.getId());
				if (vos != null && vos.size() > 0) {
				      vo.setChildren(vos);
				}
				nodes.add(vo);
			  });
	    }
	    return nodes;
      }

      private List<SysDeptViewVo> getChilderenVo(String parentId) {
	    List<SysDept> list = getChildren(parentId);
	    return buildViewVo(list);
      }

      /*
       * redis 缓存数据
       * */
      public List<SysDept> getAllList() {
	    if (redisUtil.hasKey(SystemConstant.redis_dept_data)) {
		  List<SysDept> list =
			  JSON.parseArray(
				  redisUtil.get(SystemConstant.redis_dept_data).toString(),
				  SysDept.class);
		  return list;
	    } else {
		  List<SysDept> allDept = deptMapper.selectList(null);
		  redisUtil.set(SystemConstant.redis_dept_data, JSON.toJSONString(allDept));
		  return allDept;
	    }
      }

      private void updateRedis() {
	    List<SysDept> allDept = deptMapper.selectList(null);
	    redisUtil.set(SystemConstant.redis_dept_data, JSON.toJSONString(allDept));
      }

      @Override
      public List<TreeNode> getTreeSelect() {
	    List<TreeNode> treeNodes = buildTreeNode(getParentDepts());
	    return treeNodes;
      }

      private List<SysDept> getParentDepts() {
	    List<SysDept> parentDepts =
		    this.getAllList().stream()
			    .filter(x -> StringUtils.isEmpty(x.getParentId()))
			    .sorted(Comparator.comparing(SysDept::getSortCode))
			    .collect(Collectors.toList());
	    return parentDepts;
      }

      private List<TreeNode> buildTreeNode(List<SysDept> list) {
	    List<TreeNode> treeNodes = new ArrayList<>();
	    if (list != null && list.size() > 0) {
		  list.forEach(
			  dept -> {
				TreeNode node =
					new TreeNode(dept.getId(), dept.getDeptName(), dept.getId());
				node.setData(dept);
				List<TreeNode> children = this.getChildrenNode(dept.getId());
				if (children != null && children.size() > 0) {
				      node.setLeaf(false);
				      node.setChildren(children);
				} else {
				      node.setLeaf(true);
				}
				treeNodes.add(node);
			  });
	    }
	    return treeNodes;
      }

      private List<TreeNode> getChildrenNode(String parentId) {
	    List<SysDept> list = getChildren(parentId);
	    return buildTreeNode(list);
      }

      private List<SysDept> getChildren(String parentId) {
	    LambdaQueryWrapper<SysDept> deptLambdaQueryWrapper = Wrappers.lambdaQuery();
	    deptLambdaQueryWrapper.eq(SysDept::getParentId, parentId);
	    List<SysDept> allList = this.getAllList();
	    List<SysDept> list =
		    allList.stream()
			    .filter(t -> parentId.equals(t.getParentId()))
			    .sorted(Comparator.comparing(SysDept::getSortCode))
			    .collect(Collectors.toList());
	    return list;
      }

      private SysDept getDept(String deptId) {
	    SysDept dept = deptMapper.selectById(deptId);
	    if (dept == null) {
		  throw new BusinessException(500, "未找到部门信息");
	    }
	    return dept;
      }
}
